package com.hsy.sunflowerbao.base.ui.activity

import android.app.Activity
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.print.PrintAttributes
import android.print.PrintDocumentAdapter
import android.print.PrintManager
import android.text.TextUtils
import android.view.Gravity
import android.view.KeyEvent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.webkit.WebChromeClient
import android.webkit.WebResourceError
import android.webkit.WebResourceRequest
import android.webkit.WebView
import android.webkit.WebViewClient
import android.widget.AbsListView
import android.widget.BaseAdapter
import android.widget.ImageView
import android.widget.ListPopupWindow
import android.widget.TextView

import com.flux.utils.LogUtil
import com.flux.utils.GlideUtil
import com.hsy.sunflowerbao.utils.UnitUtil
import com.hsy.sunflowerbao.R
import com.hsy.sunflowerbao.base.store.WebStore
import com.hsy.sunflowerbao.base.ui.widget.BaseWebView
import com.hsy.sunflowerbao.base.ui.widget.BaseWebViewHandler
import com.hsy.sunflowerbao.utils.CommonUtils
import kotlinx.android.synthetic.main.activity_webview.*

import org.json.JSONArray
import org.json.JSONException

/**
 * 网页Activity
 * Created on 2016/8/12.
 * Update on 2017/4/27.
 *
 * @author MartinKent, yang
 */
class WebViewActivity : BaseActivity<WebStore>(), View.OnClickListener {

    /**
     * 数据缓存器
     */
    override var store = WebStore(dispatcher)

    private lateinit var btnBack: ImageView
    private lateinit var btnClose: ImageView
    private lateinit var pageTitle: TextView
    private lateinit var btnActImg: ImageView
    private lateinit var btnActText: TextView
    private lateinit var btnActAncher: View
    private lateinit var webView: BaseWebView

    private lateinit var handler: WebViewHandler
    private var webViewContainer: ViewGroup? = null
    private var inflater: LayoutInflater? = null
    private var root: View? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        inflater = LayoutInflater.from(this)
        root = inflater!!.inflate(R.layout.activity_webview, null)
        super.setContentView(R.layout.activity_webview)
        initView()
    }

    override fun onClick(view: View) {
        if (view.id == R.id.btn_back) {
            val event = KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK)
            handler.dispatchKeyEvent(event)
        } else if (view.id == R.id.btn_close) {
            finish()
        }
    }

    private fun initView() {
        btnBack = findViewById<View>(R.id.btn_back) as ImageView
        btnBack.setOnClickListener(this)
        btnClose = findViewById<View>(R.id.btn_close) as ImageView
        btnClose.setOnClickListener(this)
        pageTitle = findViewById<View>(R.id.page_title) as TextView
        btnActImg = findViewById<View>(R.id.btn_act_img) as ImageView
        btnActText = findViewById<View>(R.id.btn_act_text) as TextView
        btnActAncher = findViewById(R.id.btn_act_ancher)
        webView = findViewById<View>(R.id.web_view) as BaseWebView

        webViewContainer = findViewById<View>(R.id.web_view_container) as ViewGroup

        handler = WebViewHandler(this)
        webView.setClient(handler)

        val intent = intent
        if (intent.hasExtra("url")) {
            var url = intent.getStringExtra("url")
            if (!url.contains("token")) {
                url += if (url.contains("?")) "&token=" + CommonUtils.getToken()
                else "?token=" + CommonUtils.getToken()
            }
            webView.loadUrl(url)
        } else {
            webView.loadUrl("file:///android_asset/index.html")
        }

        if (intent.hasExtra("shareTitle")) {
            title = intent.getStringExtra("shareTitle")
        }
        if (intent.hasExtra("backButtonVisibility")) {
            val v = intent.getIntExtra("backButtonVisibility", View.VISIBLE)
            handler.setViewVisibility(v, btnBack)
        }
    }

    fun startActivity(url: String, type: String, title: String, backButtonVisibility: Int) {
        val intent = Intent(this, WebViewActivity::class.java)
        intent.putExtra("url", url)
        intent.putExtra("type", type)
        intent.putExtra("shareTitle", title)
        intent.putExtra("backButtonVisibility", backButtonVisibility)
        super.startActivity(intent)
    }

    fun startActivityForResult(callback: String, reqCode: Int, url: String, type: String, title: String, backButtonVisibility: Int) {
        val intent = Intent(this, WebViewActivity::class.java)
        intent.putExtra("url", url)
        intent.putExtra("type", type)
        intent.putExtra("shareTitle", title)
        intent.putExtra("callback", callback)
        intent.putExtra("backButtonVisibility", backButtonVisibility)
        super.startActivityForResult(intent, reqCode)
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        handler.onActivityResult(requestCode, resultCode, data)
    }

    override fun setTitle(title: CharSequence) {
        pageTitle.text = title
    }

    override fun setTitle(titleId: Int) {
        pageTitle.text = getString(titleId)
    }

    override fun dispatchKeyEvent(event: KeyEvent): Boolean {
        val b = handler.dispatchKeyEvent(event)
        return b || super.dispatchKeyEvent(event)
    }

    private inner class WebViewHandler internal constructor(private val activity: Activity) : BaseWebViewHandler(activity) {
        private var keyEventCallback: String? = null
        private var preventKeyEventDefault = false
        private var webViewFailurePage: View? = null
        private var isErrorPage = false

        override fun onReceivedTitle(client: WebChromeClient, view: WebView, title: String) {
            if ("找不到网页" != title) {
                super.onReceivedTitle(client, view, title)
            }
        }

        override fun onPageFinished(client: WebViewClient, view: WebView, url: String) {
            super.onPageFinished(client, view, url)
            if (!isErrorPage) {
                webView?.visibility = View.VISIBLE
            }
            isErrorPage = false
        }

        override fun onReceivedError(client: WebViewClient, view: WebView, request: WebResourceRequest, error: WebResourceError) {
            isErrorPage = true
            webView?.visibility = View.GONE
            webView?.loadUrl("javascript:document.body.innerHTML='';")
            webViewFailurePage = CommonUtils.showNetworkFailure(webView?.context!!, webViewContainer!!, View.OnClickListener { _ ->
                if (null != webViewFailurePage!!.parent) {
                    webViewContainer!!.removeView(webViewFailurePage)
                }
                webView.reload()
            }, 0)
        }

        override fun shouldOverrideUrlLoading(client: WebViewClient, view: WebView, url: String): Boolean {
            btnActAncher.visibility = View.GONE
            if (url.startsWith("tel:")) {
                val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
                startActivity(intent)
                return true
            }
            view.loadUrl(url)
            return true
        }

        override fun dispatchKeyEvent(event: KeyEvent): Boolean {
            if (KeyEvent.KEYCODE_BACK == event.keyCode) {
                if (null != keyEventCallback) {
                    val cmd = "javascript:" + keyEventCallback + "(" + event.action + ")"
                    webView?.loadUrl(cmd)
                }
                if (!preventKeyEventDefault && KeyEvent.ACTION_UP == event.action) {
                    if (webView!!.canGoBack()) {
                        webView.goBack()
                    } else {
                        onCloseWindow()
                    }
                    return true
                }
                return true
            }
            return super.dispatchKeyEvent(event)
        }

        override fun onRegisterBackCallback(callback: String, preventDefault: Boolean) {
            this.keyEventCallback = callback
            this.preventKeyEventDefault = preventDefault
        }

        override fun onOpenWindow(u: String, type: String, title: String, v: Int) {
            startActivity(u, type, title, v)
        }

        override fun onOpenWindowForResult(callback: String, reqCode: Int, u: String, type: String, title: String, v: Int) {
            startActivityForResult(callback, reqCode, u, type, title, v)
        }

        override fun onCloseWindow() {
            finish()
        }

        override fun onSetFunctionButtonCallback(callback: String, args: String?) {
            val listener = OnFunctionButtonClickListener(webView!!, callback, args)
            btnActAncher.setOnClickListener(listener)
            btnActImg.setOnClickListener(listener)
            btnActText.setOnClickListener(listener)
        }

        override fun onSetFunctionButtonImageVisibility(visibility: Int) {
            setViewVisibility(visibility, btnActImg)
        }

        override fun onSetFunctionButtonImage(context: Context, img: String) {
            GlideUtil.load(activity, img, btnActImg)
            setViewVisibility(View.VISIBLE, btnActImg, btnActAncher)
            setViewVisibility(View.INVISIBLE, btnActText)
        }

        override fun onSetFunctionButtonTextVisibility(visibility: Int) {
            setViewVisibility(visibility, btnActText)
        }

        override fun onSetFunctionButtonText(text: String) {
            btnActText.text = text
            setViewVisibility(View.VISIBLE, btnActText, btnActAncher)
            setViewVisibility(View.INVISIBLE, btnActImg)
        }

        override fun onSetBackButtonVisibility(visibility: Int) {
            setViewVisibility(visibility, btnBack)
        }

        override fun onSetTitle(title: String) {
            setTitle(title)
        }

        override fun onSetFunctionButtonVisibility(visibility: Int) {
            setViewVisibility(visibility, btnActAncher)
        }

        override fun onSetFunctionButtonClickable(clickable: Boolean) {
            btnActAncher.isClickable = clickable
            btnActText.isClickable = clickable
            btnActImg.isClickable = clickable
        }

        override fun onShowDropDownMenu(items: JSONArray, callback: String?) {
            val menuAdapter = DropDownMenuAdapter(items)
            val popupWindow = ListPopupWindow(this@WebViewActivity)
            popupWindow.width = UnitUtil.dip2px(100f)
            popupWindow.setAdapter(menuAdapter)
            popupWindow.isModal = true
            popupWindow.anchorView = btnActAncher
            if (!TextUtils.isEmpty(callback)) {
                popupWindow.setOnItemClickListener { _, _, position, _ ->
                    val url = "javascript:" + callback + "(" + position + ",\"" + menuAdapter.getLabel(position) + "\",\"" + menuAdapter.getValue(position) + "\");"
                    LogUtil.d(url)
                    webView?.loadUrl(url)
                    popupWindow.dismiss()
                }
            }
            popupWindow.show()
        }

        fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
            if (null == data) {
                return
            }
            val cmd = "javascript:" + data.getStringExtra("callback") + "(" + requestCode + "," + resultCode + ",'" + data.getStringExtra("webview_data") + "')"
            LogUtil.d("onActivityResult cmd=$cmd")
            webView?.loadUrl(cmd)
        }

        override fun onFinish(data: String) {
            val intent = Intent()
            intent.putExtra("webview_data", data)
            intent.putExtra("callback", getIntent().getStringExtra("callback"))
            setResult(Activity.RESULT_OK, intent)
            finish()
        }

        private inner class OnFunctionButtonClickListener internal constructor(private val webView: WebView, private val callback: String, private val args: String?) : View.OnClickListener {
            override fun onClick(v: View) {
                val cmd: String = if (TextUtils.isEmpty(args)) {
                    "javascript:$callback();"
                } else {
                    "javascript:$callback('$args');"
                }
                LogUtil.d("OnFunctionButtonClickListener.onClick callback=$callback,args=$args,url=$cmd")
                webView.loadUrl(cmd)
            }
        }
    }

    private inner class DropDownMenuAdapter internal constructor(private val data: JSONArray) : BaseAdapter() {

        override fun getCount(): Int {
            return data.length()
        }

        override fun getItem(position: Int): Any {
            return position
        }

        override fun getItemId(position: Int): Long {
            return position.toLong()
        }

        internal fun getLabel(position: Int): String? {
            try {
                val `object` = data.getJSONObject(position)
                if (`object`.has("label")) {
                    return `object`.getString("label")
                }
            } catch (e: JSONException) {
                LogUtil.e(e.toString())
            }

            return null
        }

        internal fun getValue(position: Int): String? {
            try {
                val `object` = data.getJSONObject(position)
                if (`object`.has("value")) {
                    return `object`.getString("value")
                }
            } catch (e: JSONException) {
                LogUtil.e(e.toString())
            }

            return null
        }

        override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
            val textView: TextView
            if (null == convertView) {
                textView = TextView(this@WebViewActivity)
                textView.layoutParams = AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, UnitUtil.dip2px(32f))
                textView.gravity = Gravity.CENTER_VERTICAL
                textView.setPadding(UnitUtil.dip2px(16f), 0, 0, 0)
            } else {
                textView = convertView as TextView
            }
            textView.text = getLabel(position)
            return textView
        }
    }
}